package com.icloud.wallet.boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icloud.common.cache.service.RedisService;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.database.enums.*;
import com.icloud.common.database.mapper.AdminUserMapper;
import com.icloud.common.database.mapper.AppCustomerMapper;
import com.icloud.common.database.mapper.CustomerWalletMapper;
import com.icloud.common.database.model.AdminUser;
import com.icloud.common.database.model.AppCustomer;
import com.icloud.common.database.model.CustomerWallet;
import com.icloud.common.web.enums.StateEnum;
import com.icloud.common.web.exception.ApiException;
import com.icloud.common.web.util.AuthUtil;
import com.icloud.wallet.boot.dto.WithdrawPaymentDto;
import com.icloud.common.database.mapper.TOrderMapper;
import com.icloud.common.database.mapper.TWalletJournalMapper;
import com.icloud.wallet.boot.mapper.TWithdrawOrderItemMapper;
import com.icloud.common.database.model.TOrders;
import com.icloud.common.database.model.TWalletJournal;
import com.icloud.wallet.boot.model.TWithdrawOrderItems;
import com.icloud.wallet.boot.service.CustomerWalletService;
import com.icloud.wallet.boot.vo.WithdrawPaymentVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;


@Slf4j
@Service
public class CustomerWalletServiceImpl extends ServiceImpl<CustomerWalletMapper, CustomerWallet> implements CustomerWalletService {
    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private AppCustomerMapper appCustomerMapper;
    @Autowired
    private AdminUserMapper adminUserMapper;
    @Autowired
    private CustomerWalletMapper customerWalletMapper;
    @Autowired
    private TWithdrawOrderItemMapper tWithdrawOrderItemMapper;
    @Autowired
    private TWalletJournalMapper tWalletJournalMapper;
    @Autowired
    private AuthUtil authUtil;
    @Autowired
    private RedisService redisService;

    @Override
    public WithdrawPaymentVO withdrawPayment(WithdrawPaymentDto dto) {
        LocalDateTime now = LocalDateTime.now();
        String orderNo = dto.getOrderNo();
        if(StringUtils.isBlank(orderNo)){
            throw new ApiException(ResultCode.NOT_EXIST_ORDER_NO);
        }
        Long orderId = Long.valueOf(orderNo);
        TOrders tOrder = tOrderMapper.selectById(orderId);
        if(tOrder==null){
            throw new ApiException(ResultCode.NOT_EXIST_ORDER);
        }
        Boolean accept = dto.getAccept();
        if(accept==null){
            throw new ApiException(ResultCode.REQUIRED_ACCEPT);
        }
        Long customerId = tOrder.getCustomerId();
        AppCustomer me = appCustomerMapper.selectById(customerId);
        if(me==null){
            log.warn("Id为[{}]的前台客户不存在", customerId);
            throw new ApiException(ResultCode.NOT_EXIST_CUSTOMER);
        }
        if(StateEnum.isStop(me.getState())){
            log.warn("Id为[{}]的前台客户已被封号", customerId);
            throw new ApiException(ResultCode.STOPPED_CUSTOMER);
        }
        Long adminUserId = authUtil.getUserId();
        if(adminUserId==null){
            log.warn("审核的后台客户不存在");
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }
        AdminUser auditor = adminUserMapper.selectById(adminUserId);
        if(auditor==null){
            log.warn("审核人不存在");
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }
        LambdaQueryWrapper<TWithdrawOrderItems> withdrawQuery = new LambdaQueryWrapper<>();
        withdrawQuery.eq(TWithdrawOrderItems::getOrderId, orderId);
        TWithdrawOrderItems withdrawOrderItem = tWithdrawOrderItemMapper.selectOne(withdrawQuery);
        if(withdrawOrderItem==null){
            log.warn("订单[{}]的订单项不存在", orderId);
            throw new ApiException(ResultCode.NOT_EXIST_ORDER_ITEM);
        }
        TOrders updateOrder = TOrders.builder()
                .id(orderId)
                .paymentTime(now)
                .updatedId(adminUserId)
                .build();

        String paymentState = null;
        if(accept){
            paymentState = PaymentStateEnum.FINISHED.getCode();
        }else{
            paymentState = PaymentStateEnum.CANCEL.getCode();
            CustomerWallet wallet = customerWalletMapper.selectOne(new LambdaQueryWrapper<CustomerWallet>().eq(CustomerWallet::getCustomerId, customerId));
            if(wallet==null){
                log.warn("客户[{}]的钱包不存在", customerId);
                throw new ApiException(ResultCode.NOT_EXIST_CUSTOMER);
            }
            BigDecimal amount = tOrder.getAmount();
            BigDecimal before = wallet.getBcpc();
            BigDecimal beforeWithdrawable = wallet.getWithdrawable();
            BigDecimal after = before.add(amount);
            BigDecimal afterWithdrawable = beforeWithdrawable.add(amount);
            CustomerWallet updateWallet = CustomerWallet.builder()
                    .customerId(customerId)
                    .bcpc(after)
                    .withdrawable(afterWithdrawable)
                    .build();
            customerWalletMapper.updateById(updateWallet);
        }

        updateOrder.setPaymentState(paymentState);
        tOrderMapper.updateById(updateOrder);

        LambdaQueryWrapper<TWalletJournal> journalQuery = new LambdaQueryWrapper<>();
        journalQuery.eq(TWalletJournal::getOrderId, orderId);
        journalQuery.eq(TWalletJournal::getCustomerId, customerId);
        journalQuery.in(TWalletJournal::getJournalType, JournalTypeEnum.WITHDRAW.getCode(),
                JournalTypeEnum.WITHDRAW_ABLE.getCode());
        journalQuery.eq(TWalletJournal::getJournalState, JournalStateEnum.PENDING.getCode());
        List<TWalletJournal> withdrawJournalList = tWalletJournalMapper.selectList(journalQuery);
        if(CollectionUtils.isEmpty(withdrawJournalList)){
            log.warn("客户[{}]提现订单[{}]的流水不存在", customerId, orderId);
            throw new ApiException(ResultCode.NOT_EXIST_WALLET_JOURNAL);
        }
        if(withdrawJournalList.size()!=2){
            log.warn("客户[{}]提现订单[{}]异常", customerId, orderId);
            throw new ApiException(ResultCode.FAILED);
        }
        withdrawJournalList.forEach(j->{
            TWalletJournal updateJournal = TWalletJournal.builder()
                    .id(j.getId())
                    .updatedId(adminUserId)
                    .build();
            if(accept) {
                updateJournal.setJournalState(JournalStateEnum.FINISHED.getCode());
                updateJournal.setRemark("接受提现");
            }else{
                updateJournal.setAmount(BigDecimal.ZERO);
                updateJournal.setCharges(BigDecimal.ZERO);
                updateJournal.setAfterBalance(j.getBeforeBalance());
                updateJournal.setJournalState(JournalStateEnum.CANCEL.getCode());
                updateJournal.setRemark("拒绝提现");
            }
            tWalletJournalMapper.updateById(updateJournal);
        });

        TWithdrawOrderItems updateItem = TWithdrawOrderItems.builder()
                .id(withdrawOrderItem.getId())
                .build();

        WithdrawPaymentVO vo = new WithdrawPaymentVO();
        BeanUtils.copyProperties(dto, vo);
        if(accept) {
            updateItem.setWithdrawState(WithdrawStateEnum.HANDLED.getCode());
            vo.setWithdrawState(WithdrawStateEnum.HANDLED.getCode());
        }else{
            updateItem.setWithdrawState(WithdrawStateEnum.CANCEL.getCode());
            vo.setWithdrawState(WithdrawStateEnum.CANCEL.getCode());
        }

        tWithdrawOrderItemMapper.updateById(updateItem);
        return vo;
    }
}
